package armserver.server;

import java.io.Serializable;
import java.util.Iterator;
import java.util.Map;

import javax.management.InstanceAlreadyExistsException;
import javax.management.MBeanRegistrationException;
import javax.management.MBeanServer;
import javax.management.MalformedObjectNameException;
import javax.management.NotCompliantMBeanException;
import javax.management.Notification;
import javax.management.NotificationBroadcasterSupport;
import javax.management.ObjectName;

import org.apache.log4j.Logger;

import armserver.context.ArmServerContext;
import armserver.context.ArmServerContextImpl;
import armserver.deploy.ArmDeploy;
import armserver.jms.wmq.JmsConnectFactory;

public class ArmServerController extends NotificationBroadcasterSupport
		implements ArmServerControllerMBean,Serializable {

	private static final Logger log = Logger.getLogger(ArmServerController.class);
	private MBeanServer server;
	private ArmServerContext context;
	private boolean running;
	private static final String OBJECTNAME = ArmServerConstant.DEFAUTL_DOMAIN+ ":service=ArmServerController";
	private static final String DEPLOYMENT = "DEPLOYMENT";
	private static final String REMOVEDEPLOYMENT = "REMOVEDEPLOYMENT";
	private static final String DEPLOYMENT_SUCCESS = " deployment mbean successful";
	private static final String DEPLOYMENT_FAILD = "deployment mbean faild";
	private static final String REMOVEDEPLOYMENT_SUCCESS = "remove deployment mbean successful";
	private static final String REMOVEDEPLOYMENT_FAILD = "remove deployment mbean faild";

	private ArmServerController() {
	};

	private static ArmServerController instance = new ArmServerController();

	public static ArmServerController getInstance() {
		if (instance == null) {
			return new ArmServerController();
		}
		return instance;
	}

	private void init() {
		context = new ArmServerContextImpl();
		this.addNotificationListener(new ArmServerControllerListener(), null,
				this);
	}

	public void deployment(Object mbean, String objectName) throws Exception {

		if (objectName != null) {
			this.deployment(mbean, new ObjectName(objectName));
		}
	}

	public void deployment(Object mbean, ObjectName objectName)
			throws Exception {
		server.registerMBean(mbean, objectName);
		if (context.containsKey(objectName)) {
			this.sendNotification(new Notification(this.DEPLOYMENT, mbean, 0,
					System.currentTimeMillis(), this.DEPLOYMENT_FAILD));
			throw new Exception(objectName.getCanonicalName()
					+ "exist at MBeanServer cann`t registry");
		}
		context.put(objectName, mbean);
		this.sendNotification(new Notification(this.DEPLOYMENT, mbean, 0,
				System.currentTimeMillis(), this.DEPLOYMENT_SUCCESS));
	}

	public void removeDeployment(ObjectName objectName) throws Exception {

		server.unregisterMBean(objectName);
		if (context.containsKey(objectName)) {
			context.remove(objectName);
			this.sendNotification(new Notification(this.REMOVEDEPLOYMENT,
					objectName, 0, System.currentTimeMillis(),
					this.REMOVEDEPLOYMENT_SUCCESS));
		}
		else{
		    this.sendNotification(new Notification(this.REMOVEDEPLOYMENT,objectName, 0, System.currentTimeMillis(),
				this.REMOVEDEPLOYMENT_FAILD));
		}
	}

	public void deployment(Object mbean, String objectName,
			Map<ObjectName, String> dependenceMap) throws Exception {

		if (dependenceMap == null || dependenceMap.isEmpty()) {
			this.deployment(mbean, objectName);
			return;
		}

		Iterator it = dependenceMap.keySet().iterator();
		while (it.hasNext()) {
			ObjectName on = (ObjectName) it.next();
			if (!context.containsKey(on)) {
				String className = dependenceMap.get(on);
				Class clazz = Class.forName(className);
				if (clazz == null) {
					throw new Exception(className + " not found");
				}
				Object obj = clazz.newInstance();
				server.registerMBean(obj, on);
				context.put(on, obj);
			}
		}

	}

	public void start() throws Exception {
		init();
		server.registerMBean(this, ObjectName.getInstance(OBJECTNAME));
		running = true;

	}

	public void stop() throws Exception {
		context.clear();
		server.unregisterMBean(ObjectName.getInstance(OBJECTNAME));
		running = false;

	}

	public void setMBeanServer(MBeanServer mbeanServer) {
		this.server = mbeanServer;

	}

	public void install() throws ArmException {
    
		ArmDeploy deploy = new ArmDeploy();
		try {
			server.registerMBean(deploy, new ObjectName(ArmDeploy.deployName));
		} catch (InstanceAlreadyExistsException e) {
			e.printStackTrace();
		} catch (MBeanRegistrationException e) {
			e.printStackTrace();
		} catch (NotCompliantMBeanException e) {
			e.printStackTrace();
		} catch (MalformedObjectNameException e) {
			e.printStackTrace();
		} catch (NullPointerException e) {
			e.printStackTrace();
		}

	}

	public void uninstall() throws ArmException {

	}


}
